use sqlx::{MySqlPool};

use crate::{errors::AppError, models::User};

use uuid::Uuid;

use chrono::{Utc};

// #[derive(Debug , FromRow)]
// struct UserRow {
//     pub id: Uuid,
//     username: String,
//     email: String,
//     password_hash: String,
//     created_at: chrono::DateTime<chrono::Utc>,
//     updated_at: chrono::DateTime<chrono::Utc>,
// }

pub async fn create_user(
    pool: &MySqlPool,
    username: &str,
    email: &str,
    password_hash: &str,
) -> Result<User, AppError> {
    let uuid = Uuid::new_v4();
    let user_id_str = uuid.to_string();
   sqlx::query_as!(
        User,
        r#"
        INSERT INTO users (id, username, email, password_hash) VALUES (?, ?, ?, ?)"#,
        user_id_str,
        username,
        email,
        password_hash
    )
    .fetch_one(pool)
    .await
    .map_err(|e| AppError::BadRequest(e.to_string()))?;

    let user = get_user_by_id(pool,&user_id_str);
    Ok(user.await?)
}

pub async fn find_user_by_email(
    pool: &MySqlPool, email: &str
) -> Result<User,AppError> {
    let row = sqlx::query!(
        "SELECT * FROM users WHERE email = ?", 
        email
        )
        .fetch_one(pool)
        .await
        .map_err(|_| AppError::InternalServerError("用户不存在".to_string()))?;
    let user = User {
        id: row.id,
        username: row.username.expect("msg"),
        email: row.email.expect("msg"),
        password_hash: row.password_hash.expect("msg"),
        created_at: row.created_at.expect("msg"),
        updated_at: row.updated_at.expect("msg"),
    };
    Ok(user)
}

pub async fn get_all_users(pool: &MySqlPool) -> Result<Vec<User>, AppError> {
    let rows = sqlx::query!("SELECT * FROM users")
        .fetch_all(pool)
        .await?;

    let users = rows
    .into_iter()
    .map(|row| User {
        id: row.id,
        username: row.username.expect(""),
        email: row.email.expect(""),
        password_hash: row.password_hash.expect("msg"),
        created_at: row.created_at.expect("msg"),
        updated_at: row.updated_at.expect("msg"),
    })
    .collect();
    Ok(users)
}

pub async fn get_user_by_id(pool: &MySqlPool, id: &String) -> Result<User, AppError> {
    let row = sqlx::query!( "SELECT * FROM users WHERE id = ?", id)
        .fetch_one(pool)
        .await
        .map_err(|e| match e {
            sqlx::Error::RowNotFound => AppError::InternalServerError("用户不存在".to_string()),
            _ => AppError::DatabaseError(e.into()),
        })?;
    let user = User {
        id: row.id,
        username: row.username.expect("username"),
        email: row.email.expect("email"),
        password_hash: row.password_hash.expect("password_hash"),
        created_at: row.created_at.unwrap_or_else(|| Utc::now()),
        updated_at: row.updated_at.unwrap_or_else(|| Utc::now()),
    };
    Ok(user)
}